/**
 * TranslateServlet.java
 *
 * Copyright (C) 2009,  Tomislav Milkovic
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package extjsdyntran.servlets;

import java.io.*;
//import java.net.Authenticator;
import java.util.*;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.json.JSONObject;

import extjsdyntran.translation.TranslationAbstract;
import extjsdyntran.translation.TranslationFactory;
import extjsdyntran.translation.TranslationIntf;


/**
 * @description  Main translation servlet responsible for initialization of translation services and
 * translations itself
 */
public class TranslateServlet extends HttpServlet implements Servlet {
	private static final long serialVersionUID = 1L;
	
	public void destroy() {
		TranslationFactory.saveLanguages("*");
		super.destroy();
	}

	public void init(ServletConfig conf) throws ServletException {
		super.init(conf);
		
		String store = "";
		File file = new File((String) conf.getInitParameter(Constants.prop_store_path));
		if (!file.exists()) {
			System.out.println("Directroy does not exists for..");
			System.out.println("property : " + (String) Constants.prop_store_path);
			System.out.println("value    : " + (String) conf.getInitParameter(Constants.prop_store_path));
			String value = ((File) getServletContext().getAttribute("javax.servlet.context.tempdir")).getPath();
			
			store = value + System.getProperty("file.separator");
			System.out.println("Using server temporary path : " + value);
		}
		
		Enumeration<?> initParams = conf.getInitParameterNames();
		while (initParams.hasMoreElements()) {
			String key = (String) initParams.nextElement();
			String value = conf.getInitParameter(key);
			if(!key.startsWith(Constants.prop_service)) continue;
			
			try{
			TranslationFactory.appendService( value,
										  (String) conf.getInitParameter(Constants.prop_proxy_user),
										  (String) conf.getInitParameter(Constants.prop_proxy_password),
										  store);
			}catch(Exception e){
				new ServletException(e);
			}
		}
		
		if (TranslationFactory.size()==0) new ServletException("Translation service not set!");
				
		
	}


	
	private String getResponse(boolean status, String msg) {
		try{
			JSONObject res = new JSONObject();
			res.put("success", status);
			if (msg!=null) 	res.put("msg",msg);
			return res.toString();
		}catch(Exception e){
			return Constants.json_false;
		}
	}
	
	private void setResponseHeader(HttpServletResponse response){
		// Set to expire far in the past.
		response.setDateHeader("Expires", 0);
		// Set standard HTTP/1.1 no-cache headers.
		response.setHeader("Cache-Control",	"no-store, no-cache, must-revalidate");
		// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
		response.addHeader("Cache-Control", "post-check=0, pre-check=0");
		// Set standard HTTP/1.0 no-cache header.
		response.setHeader("Pragma", "no-cache");

		// return a
		response.setContentType("text/plain; charset=UTF-8");
	}
	/*
	 * GET options
	 * 
	 * Returns json boolean result; test for availability of Google Translation
	 * Service API TranslateServlet?cmd=test
	 * 
	 * Retrieves list of supported languages for translation; if reload added
	 * then cached translations are reloaded from cache
	 * TranslateServlet?cmd=languages&reload
	 * 
	 * Translates defined text to defined language where 'xxxxx' is text to
	 * translate TranslateServlet?cmd=translate&translate=xxxxx&language=CROATIAN
	 * 
	 * Serialize defined language to language file
	 * TranslateServlet?cmd=store&language=CROATIAN
	 * 
	 * Serailize all supported languages to language files
	 * TranslateServlet?cmd=store&language=*
	 * 
	 * Returns json list of all stored translations for requested language
	 * TranslateServlet?cmd=load&language=CROATIAN
	 */
	protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {

		setResponseHeader(response);
		Map<String, String> pmap = request.getParameterMap();
		
		if (!pmap.containsKey(Constants.param_command)) {
			PrintWriter pw = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), "UTF8"), true);
			pw.print(getResponse(false, Constants.err3));
			pw.flush();
			pw.close();
			return;
		};
		
		String cmd =  request.getParameter(Constants.param_command);
			
		if (Constants.cmd_export.equals(cmd)) {
			try{
				doExport(request,response);
			}catch(Exception e){
				e.printStackTrace();
			}
			return;
		};
		
		
		// UTF-8 writer
		PrintWriter pw = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), "UTF8"), true);

		//test for remote service
		// TODO test specific service , if all services, return array of messages which service is working, if simple test just do all services
		if (Constants.cmd_test.equals(cmd)) {
			JSONObject jobj = new JSONObject();
			if(TranslationFactory.test(jobj) == true) {
				pw.print(Constants.json_true);
			} else
				pw.print(getResponse(false, Constants.err4));

		//get list of supported languages; reload translations if needed
		} else if (Constants.cmd_languages.equals(cmd)) {

			pw.print(TranslationFactory.getLanguages());
			if (pmap.containsKey(Constants.param_reloadlanguages)) {
				TranslationFactory.reloadLanguages();
			}

		//translate value to speciffied language	
		} else if (Constants.cmd_translate.equals(cmd)) {
			
			String value = request.getParameter(Constants.cmd_translate);
			String language =  request.getParameter(Constants.param_language);
			
			if ((value!=null)&&(language!=null)) {
				TranslationIntf  transervice= TranslationFactory.getService(language);
				pw.print(transervice.translate(value,language));
			} else
				pw.print(getResponse(false, Constants.err5));

		//request save translation cache to disk	
		} else if (Constants.cmd_store.equals(cmd)) {
			
			String language =  request.getParameter(Constants.param_language);
			if (language != null) {
				pw.print(getResponse(false, Constants.err7));
			};
			TranslationIntf  transervice= TranslationFactory.getService(language);
			if (transervice.saveLanguages(language)) {
				pw.print(Constants.json_true);
			} else {
				pw.print(getResponse(false, Constants.err6));
			}
		
		//request load translation cache from disk
		} else if (Constants.cmd_load.equals(cmd)) {
			
			String language =  request.getParameter(Constants.param_language);
			if (language != null) {
				TranslationIntf  transervice= TranslationFactory.getService(language);
				pw.print(transervice.getTranslations(language));
			}else {
				pw.print(getResponse(false, Constants.err7));
			}
		
		//remove language from cache
		} else if (Constants.cmd_remove.equals(cmd)) {
			String language =  request.getParameter(Constants.param_language);
			if (language != null) {
				TranslationIntf  transervice= TranslationFactory.getService(language);
				if(!transervice.removeLanguageFromCache(language)){
					pw.print(getResponse(false, Constants.err8));	
				} else pw.print(getResponse(true, null));
			}else {
				pw.print(getResponse(false, Constants.err1));
			}
			
		
		//add new language to cache
		} else if (Constants.cmd_add.equals(cmd)) {

			String language =  request.getParameter(Constants.param_language);
			if (language != null) {
				while(true){
				if (language.length()<3){
					pw.print(getResponse(false, Constants.err13));
					break;
				}
				TranslationIntf  transervice= TranslationFactory.getEditableService(language);
				if(transervice==null){
						pw.print(getResponse(false, Constants.err12));
				} else	if(!transervice.appendLanguageFromCache(language)){
						pw.print(getResponse(false, Constants.err9));	
				} else pw.print(getResponse(true, null));
				break;
				}
			}else {
				pw.print(getResponse(false, Constants.err1));
			}
		} 

		pw.flush();
		pw.close();

	}

	protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
		
		setResponseHeader(response);

		// UTF-8 writer
		PrintWriter pw = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), "UTF8"), true);
		
		Map<?, ?> pmap = request.getParameterMap();
		
		boolean isMultipart = ServletFileUpload.isMultipartContent(request);		
		if (isMultipart){
			try{
				if (doImport(request)) {
					pw.print(Constants.json_true);	
				} else pw.print(getResponse(false, Constants.err10)); 
				
			}catch(Exception e){
				pw.print(getResponse(false, e.getMessage()));
				e.printStackTrace();
			}
			
			pw.flush();
			pw.close();
			return;
		}


		
		if (pmap.containsKey(Constants.param_action)) {
			
			if (pmap.containsKey(Constants.param_language)) {
				String action[] = request.getParameterValues(Constants.param_action);
				String lang[] = request.getParameterValues(Constants.param_language);
				String rows[] = request.getParameterValues(Constants.param_data);
				String r = getResponse(false, Constants.err11);
				TranslationAbstract service = (TranslationAbstract)TranslationFactory.getService(lang[0]);
				if ("read".equals(action[0])){				
					r = service.getTranslationRecords(lang[0]);	
				}else if ("destroy".equals(action[0])){
					 r = service.deleteRecords(lang[0],rows[0]);
				}else if ("update".equals(action[0])){ 
					 r = service.updateRecords(lang[0],rows[0]);
				}else if ("create".equals(action[0])){
					 r = service.createRecords(lang[0],rows[0]);					
				};
				
				pw.print(r);
				
			}else {
				pw.print(getResponse(false, Constants.err3));
			}
			
			pw.flush();
			pw.close();
		}		

	}

	//compress language cache files and send to client
	private void doExport(HttpServletRequest request,HttpServletResponse response) throws Exception {

		
		boolean isSingle = request.getParameter(Constants.param_language)!=null; 
		ByteArrayOutputStream bout = null;
		
		if (isSingle) {
			String language = request.getParameter(Constants.param_language);
			response.setHeader("Content-Disposition","inline; filename="+language+".transl;");
			TranslationFactory.saveLanguages(language);
			bout = TranslationFactory.compressCache(language);
		}else{
			response.setHeader("Content-Disposition","inline; filename=all.transl;");
			TranslationFactory.saveLanguages("*");
			bout = TranslationFactory.compressCache(null);
		}

		setResponseHeader(response);
		response.setContentType("application/zip");		
		ServletOutputStream out = response.getOutputStream(); 
		out.write(bout.toByteArray());
        out.flush();
	}

	//receive compressed language files;decompress to cache
	private boolean doImport(HttpServletRequest request ) throws Exception {
		
		
		FileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload upload = new ServletFileUpload(factory);
		List<?> items = upload.parseRequest(request);
		boolean result = false;
		Iterator<?> iter = items.iterator();
		while (iter.hasNext()) {
		    FileItem item = (FileItem) iter.next();

		    if (item.isFormField()) {
		    	
		    } else {
				try{
					if (TranslationFactory.deCompressCache(item)){
						TranslationFactory.saveLanguages("*");
						return true;
					}
					return false;
				}catch(Exception e ){
					e.printStackTrace();
				}
		    }
		}
		
		return false;
		
	}
	

	
}
